package socket;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天室客户端
 *
 * @author Luka
 * @date 2021/06/02 14:26
 **/
public class Client {
    /*
        java.net.Socket套接字
        Socket封装了TCP协议的通讯细节,使得我们可以用它与服务端建立TCP连接,并
        通过它获取两个流(一个输入一个输出),且基于这两个六的读写字节操作完成与
        远端(服务端)计算机的通讯
    */
    private Socket socket;

    /*
    * 构造方法 用于初始化客户端
    * */
    public Client() {
        try {
             /*
            实例化Socket时经常用的工造方法需要我们传入两个参数
            参数1:远端计算机的IP地址信息
            参数2:远端计算机开启的服务端口
            对于客户端这边儿研,远端指的是服务端
            通过IP可以找到网络上的服务端计算机,通过端口连接到该机器上运行的
            服务端应用程序(这个端口就是改程序在服务端计算机上申请并打开的)
            (谁发起连接谁是客户端)
         */
            System.out.println("正在连接服务端...");
            socket = new Socket("localhost",8088);
            System.out.println("与服务端建立连接!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
    * 客户端开始工作的方法
    * */
    public void start(){
        try {
            //首先启动用于读取服务端发送过来消息的线程
            serverHandler handler = new serverHandler();
            Thread t = new Thread(handler);
            t.start();


            /*
                Socket提供的方法:
                OutputStream getOutputStream()
                通过该方法获取一个字节输出流,使用这个字节输出流写出的字节会发送
                给远端计算机
             */
            Scanner sc = new Scanner(System.in);
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw,true);


            System.out.println("开始聊天,按输入exit退出");
            while (true){
                String input = sc.nextLine();
                if(input.equals("exit")) {
                    break;
                }
                pw.println(input);

            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                /*
                    通讯完毕最终要关闭socket
                    该方法会给远端计算机TCP断开信号,通知远端计算机要断开TCP

                 */
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    private class serverHandler implements Runnable{
        @Override
        public void run() {
            try {
                //通过socket获取输入流，读取服务端发送过来的消息
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(
                                socket.getInputStream(),"UTF-8"
                        )
                );
                String line;
                //循环读取服务端发送过来的每一行字符串
                while((line = br.readLine())!=null){
                    System.out.println(line);//将读取到的字符串输出到控制台
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}